package com.zxjbyte.yiyi.module.system.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.cglib.CglibUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zxjbyte.yiyi.framework.common.domain.api.PageResult;
import com.zxjbyte.yiyi.framework.common.util.AuthUtil;
import com.zxjbyte.yiyi.framework.common.util.CollXUtil;
import com.zxjbyte.yiyi.framework.mybatis.service.impl.BaseServiceXImpl;
import com.zxjbyte.yiyi.framework.mybatis.util.Condition;
import com.zxjbyte.yiyi.framework.mybatis.util.UniqueChecker;
import com.zxjbyte.yiyi.module.system.domain.entity.DictPO;
import com.zxjbyte.yiyi.module.system.domain.param.dict.DictAddParam;
import com.zxjbyte.yiyi.module.system.domain.param.dict.DictListParam;
import com.zxjbyte.yiyi.module.system.domain.param.dict.DictUpdateParam;
import com.zxjbyte.yiyi.module.system.domain.vo.DictListVO;
import com.zxjbyte.yiyi.module.system.domain.vo.DictVO;
import com.zxjbyte.yiyi.module.system.enums.DictTypeEnum;
import com.zxjbyte.yiyi.module.system.mapper.DictMapper;
import com.zxjbyte.yiyi.module.system.service.DictService;
import com.zxjbyte.yiyi.module.system.util.cache.DictCacheUtil;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.zxjbyte.yiyi.framework.common.enums.SortOrder.DESC;
import static com.zxjbyte.yiyi.framework.common.util.ValidationUtil.*;

/**
 * @Author zhangxingjia
 * @Date 2024/1/24 16:18
 * @Version: 1.0
 */
@Service
public class DictServiceImpl extends BaseServiceXImpl<DictMapper, DictPO> implements DictService {


    @Override
    public PageResult<DictListVO> list(DictListParam param) {
        LambdaQueryWrapper<DictPO> wrapper = Wrappers.<DictPO>lambdaQuery().eq(Objects.nonNull(param.getId()), DictPO::getId, param.getId())
                .eq(DictPO::getType, param.getType())
                .like(StrUtil.isNotBlank(param.getDictName()), DictPO::getDictName, param.getDictName());
        IPage<DictPO> page = page(Condition.getPage(param, DictPO::getCreateTime, DESC), wrapper);
        List<DictPO> records = page.getRecords();
        List<DictListVO> voList = null;
        if(CollXUtil.isNotEmpty(records)){
            voList = CglibUtil.copyList(records, DictListVO::new);
        }
        return PageResult.of(voList, page);
    }

    @Override
    public DictVO detail(Long id) {
        DictPO entity = getById(id);
        assertNotNull(entity, () -> "字典不存在");
        return CglibUtil.copy(entity, DictVO.class);
    }

    @Override
    public void add(DictAddParam param) {
        checkDict(null, param.getDictCode());
        DictPO entity = new DictPO();
        CglibUtil.copy(param, entity);
        Date now = new Date();
        String userName = AuthUtil.getUserName();
        entity.setCreateTime(now);
        entity.setCreateUser(userName);
        entity.setUpdateTime(now);
        entity.setUpdateUser(userName);
        save(entity);
    }

    @Override
    public void update(DictUpdateParam request) {
        DictPO dictPo = checkDict(request.getId(), request.getDictCode());
        assertFalse(Objects.equals(dictPo.getType(), DictTypeEnum.SYSTEM_DICT.getCode())
                && !Objects.equals(dictPo.getDictCode(), request.getDictCode()), "系统内置字典code不可更改");
        lambdaUpdate().set(DictPO::getType, request.getType())
                .set(DictPO::getDictName, request.getDictName())
                .set(DictPO::getDictCode, request.getDictCode())
                .set(DictPO::getRemark, StrUtil.nullToEmpty(request.getRemark()))
                .set(DictPO::getUpdateTime, new Date())
                .set(DictPO::getUpdateUser, AuthUtil.getUserName())
                .eq(DictPO::getId, request.getId()).update();
        DictCacheUtil.renameDictKey(dictPo.getDictCode(), request.getDictCode());
    }

    @Override
    public List<DictPO> getByType(String type) {
        return lambdaQuery().eq(DictPO::getType, type).list();
    }

    private DictPO checkDict(Long id, String dictCode){
        DictPO dictPo = null;
        assertFalse(id != null && (dictPo = getById(id)) == null, "当前字典不存在");
        assertTrue(UniqueChecker.of(this).where(DictPO::getDictCode, dictCode).ignoreId(id).check(), "字典code已存在");
        return dictPo;
    }
}
